/*
    DLL Unhooking Method 2
    @5mukx
    Resource covered from ired.team
 */ 

use std::io::{self, ErrorKind, Result};
use std::ptr::null_mut;

use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
use winapi::um::handleapi::CloseHandle;
use winapi::um::libloaderapi::GetModuleHandleA;
use winapi::um::memoryapi::{CreateFileMappingW, MapViewOfFile, UnmapViewOfFile, FILE_MAP_READ};
use winapi::um::processthreadsapi::GetCurrentProcess;
use winapi::um::psapi::{GetModuleInformation, MODULEINFO};
use winapi::um::winnt::{FILE_SHARE_READ, GENERIC_READ, PAGE_READONLY, SEC_IMAGE};

fn main() -> Result<()> {
    unsafe {
        let process = GetCurrentProcess();
        let ntdll_module = GetModuleHandleA("ntdll.dll\0".as_ptr() as *const i8);

        if ntdll_module.is_null() {
            eprintln!("[-] Failed to get ntdll.dll handle");
            return Err(io::Error::new(ErrorKind::Other, "Failed to get ntdll handle"));
        }

        println!("[+] Process Info: {:?}", process);

        let mut mi = MODULEINFO {
            lpBaseOfDll: null_mut(),
            SizeOfImage: 0,
            EntryPoint: null_mut(),
        };

        let success = GetModuleInformation(
            process,
            ntdll_module,
            &mut mi,
            std::mem::size_of::<MODULEINFO>() as u32,
        );

        if success == 0 {
            return Err(io::Error::new(ErrorKind::Other, "Failed to get module information"));
        }

        let ntdll_path = "C:\\windows\\system32\\ntdll.dll";
        let ntdll_path_utf16: Vec<u16> = ntdll_path.encode_utf16().chain(Some(0)).collect();
        let ntdll_file = CreateFileW(
            ntdll_path_utf16.as_ptr(),
            GENERIC_READ,
            FILE_SHARE_READ,
            null_mut(),
            OPEN_EXISTING,
            0,
            null_mut(),
        );

        if ntdll_file.is_null() {
            return Err(io::Error::last_os_error());
        }

        println!("ntdll_file Handle: {:?}", ntdll_file);

        let ntdll_mapping = CreateFileMappingW(
            ntdll_file,
            null_mut(),
            PAGE_READONLY | SEC_IMAGE,
            0,
            0,
            null_mut(),
        );

        if ntdll_mapping.is_null() {
            CloseHandle(ntdll_file);
            return Err(io::Error::last_os_error());
        }

        println!("CreateFileMappingW: {:?}", ntdll_mapping);

        let ntdll_mapping_addr = MapViewOfFile(
            ntdll_mapping,
            FILE_MAP_READ,
            0,
            0,
            0,
        );

        if ntdll_mapping_addr.is_null() {
            CloseHandle(ntdll_mapping);
            CloseHandle(ntdll_file);
            return Err(io::Error::last_os_error());
        }

        println!("ntdll mapping addr: {:?}", ntdll_mapping_addr);

        UnmapViewOfFile(ntdll_mapping_addr);
        CloseHandle(ntdll_mapping);
        CloseHandle(ntdll_file);
    }

    Ok(())
}

